package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"jsengine/interpreter"
	"jsengine/lexer"
	"jsengine/parser"
)

func main() {
	// 定义命令行参数
	var (
		jscode   string
		filename string
		debug    bool
	)

	flag.StringVar(&jscode, "code", "", "JavaScript code to execute")
	flag.StringVar(&filename, "f", "", "JavaScript file to execute")
	flag.BoolVar(&debug, "debug", false, "Enable debug mode")
	flag.Parse()

	// 检查参数
	if jscode == "" && filename == "" {
		fmt.Println("使用方法: jsengine <javascript代码> 或 jsengine -f <javascript文件>")
		return
	}

	var code string
	if filename != "" {
		// 从文件读取代码
		content, err := ioutil.ReadFile(filename)
		if err != nil {
			fmt.Printf("无法读取文件: %s\n", err)
			return
		}
		code = string(content)
	} else {
		code = jscode
	}

	// 创建词法分析器
	l := lexer.New(code)

	// 创建语法分析器
	p := parser.New(l)

	// 解析程序
	program := p.ParseProgram()

	// 检查解析错误
	if len(p.Errors()) != 0 {
		fmt.Printf("解析器错误数量: %d\n", len(p.Errors()))
		for i, err := range p.Errors() {
			fmt.Printf("错误 %d: %s\n", i+1, err)
		}

		fmt.Printf("错误信息详情数量: %d\n", len(p.ErrorsInfo()))
		for _, errInfo := range p.ErrorsInfo() {
			// 打印错误信息
			fmt.Printf("\033[31m错误: %s\033[0m\n", errInfo.Message)

			// 打印源代码行
			if errInfo.CodeLine != "" {
				fmt.Printf("%d | %s\n", errInfo.Line, errInfo.CodeLine)

				// 打印错误位置指示器
				spaces := "   " // 行号前的空格，对齐
				for i := 0; i < errInfo.Line/10; i++ {
					spaces += " " // 根据行号的位数调整空格数量
				}
				spaces += " | " // 竖线后的空格

				// 在错误位置下方添加波浪线
				wavePointer := spaces
				for i := 0; i < errInfo.Column; i++ {
					wavePointer += " "
				}
				wavePointer += "\033[31m^\033[0m" // 红色的错误指示符号

				// 输出波浪线指示器
				fmt.Println(wavePointer)
			}

			fmt.Println() // 添加一行空行使错误更加清晰
		}
		return
	}

	// 调试模式下打印AST
	if debug {
		fmt.Println("===== AST =====")
		fmt.Println(program.String())
		fmt.Println("==============")
	}

	// 创建解释器
	evaluator := interpreter.New()

	// 执行程序
	result := evaluator.Eval(program)

	// 如果执行过程中发生错误，打印错误信息
	if result != nil {
		if _, ok := result.(*interpreter.Error); ok {
			fmt.Printf("执行错误: %s\n", result.Inspect())
			return
		}
	}

	// 只在debug模式下打印结果
	if result != nil && debug {
		fmt.Printf("执行结果: %s\n", result.Inspect())
	}
}
